home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / net / ds5000.md / netLEXmit.c < prev   
C/C++ Source or Header  |  1991-04-08  |  22KB  |  783 lines

  1. /* 
  2.  * netLEXmit.c --
  3.  *
  4.  *    Routines to transmit packets on the LANCE interface.
  5.  *
  6.  * Copyright 1988 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/kernel/net/sun3.md/RCS/netLEXmit.c,v 9.9 91/04/08 14:04:22 jhh Exp $ SPRITE (Berkeley)";
  19. #endif
  20.  
  21. #include <sprite.h>
  22. #include <sys.h>
  23. #include <netLEInt.h>
  24. #include <vm.h>
  25. #include <vmMach.h>
  26. #include <list.h>
  27. #include <sync.h>
  28. #include <machMon.h>
  29.  
  30. /*
  31.  * Macros to step ring pointers.
  32.  */
  33.  
  34. #define    NEXT_SEND(p)    ( ((p+1) > statePtr->xmitDescLastPtr) ? \
  35.                 statePtr->xmitDescFirstPtr : \
  36.                 (p+1))
  37. #define    PREV_SEND(p)    ( ((p-1) < statePtr->xmitDescFirstPtr) ? \
  38.                 statePtr->xmitDescLastPtr : \
  39.                 (p-1))
  40. static    ReturnStatus    OutputPacket _ARGS_((Net_EtherHdr *etherHdrPtr,
  41.                 Net_ScatterGather *scatterGatherPtr,
  42.                 int scatterGatherLength,
  43.                 NetLEState *statePtr));
  44. static    void        AllocateXmitMem _ARGS_((NetLEState *statePtr));
  45.  
  46. char    foo[NET_ETHER_MAX_BYTES];
  47.  
  48. /*
  49.  *----------------------------------------------------------------------
  50.  *
  51.  * OutputPacket --
  52.  *
  53.  *    Assemble and output the packet in the given scatter/gather element.
  54.  *    The ethernet header contains the address of the destination host
  55.  *    and the higher level protocol type already.
  56.  *
  57.  * Results:
  58.  *    FAILURE if something went wrong.
  59.  *
  60.  * Side effects:
  61.  *    Transmit command list is modified to contain the packet.
  62.  *
  63.  *----------------------------------------------------------------------
  64.  */
  65.  
  66. static ReturnStatus
  67. OutputPacket(etherHdrPtr, scatterGatherPtr, scatterGatherLength, statePtr)
  68.     Net_EtherHdr        *etherHdrPtr;    /* Ethernet header of packet.*/
  69.     register    Net_ScatterGather       *scatterGatherPtr; /* Data portion of
  70.                                 * packet. */
  71.  
  72.     int            scatterGatherLength;    /* Length of data portion 
  73.                          * gather array. */
  74.     NetLEState        *statePtr;        /* The interface state. */
  75. {
  76.     register volatile NetLEXmitMsgDesc    *descPtr;
  77.     register    char            *firstBufferPtr; 
  78.     Address                bufPtr;
  79.     int                    bufCount;
  80.     int                    totalLength;
  81.     int                    length;
  82.     int                    amountNeeded;
  83. #if defined(sun3) || defined(sun4)
  84.     Net_ScatterGather            newScatGathArr[NET_LE_NUM_XMIT_BUFFERS];
  85.     register Boolean            reMapped = FALSE;
  86. #endif
  87.     int                    i;
  88.  
  89.     descPtr = statePtr->xmitDescNextPtr;
  90.  
  91.     /*
  92.      * Do some sanity checks.
  93.      */
  94.     if (NetBfByteTest(descPtr->bits1, ChipOwned, 1)) {
  95.     printf("LE ethernet: Transmit buffer owned by chip.\n");
  96.     return (FAILURE);
  97.     }
  98.  
  99.     statePtr->transmitting = TRUE;
  100.     statePtr->curScatGathPtr = scatterGatherPtr;
  101.     firstBufferPtr = statePtr->firstDataBuffer;
  102.  
  103.     /*
  104.      * Add the first data buffer to the ring.
  105.      */
  106.     descPtr->bufAddrLow = NET_LE_TO_CHIP_ADDR_LOW(firstBufferPtr);
  107.     descPtr->bufAddrHigh = NET_LE_TO_CHIP_ADDR_HIGH(firstBufferPtr);
  108.     NetBfByteSet(descPtr->bits1, StartOfPacket, 1);
  109.     NetBfByteSet(descPtr->bits1, EndOfPacket, 0);
  110.  
  111.     /*
  112.      * Since the first part of a packet is always the ethernet header that
  113.      * is less than NET_LE_MIN_FIRST_BUFFER_SIZE we must use the 
  114.      * firstDataBuffer to build the first buffer of mimumum allowable size.
  115.      */
  116.  
  117.  
  118.     descPtr->bufferSize = -NET_LE_MIN_FIRST_BUFFER_SIZE; /* May be wrong 
  119.                               * for small 
  120.                               * packets. 
  121.                               */
  122.  
  123.     /* 
  124.      * First copy in the header making sure the source address field is set
  125.      * correctly. (Such a fancy chip and it won't even set the source 
  126.      * address
  127.      * of the header for us.)
  128.      */
  129.  
  130.     (* ((Net_EtherHdr *) firstBufferPtr)) = *etherHdrPtr;
  131.  
  132.     ((Net_EtherHdr *) firstBufferPtr)->source = statePtr->etherAddress;
  133.  
  134.     firstBufferPtr += sizeof(Net_EtherHdr);
  135.  
  136.     if (NET_LE_COPY_PACKET) {
  137.     totalLength = sizeof(Net_EtherHdr);
  138.     for (i = 0; i < scatterGatherLength; i++) {
  139.         totalLength += scatterGatherPtr[i].length;
  140.     } 
  141.     if (totalLength <= NET_ETHER_MAX_BYTES) {
  142.         Net_GatherCopy(scatterGatherPtr, scatterGatherLength, 
  143.         firstBufferPtr);
  144.         descPtr->bufferSize = -totalLength;
  145.     } else {
  146.         panic("OutputPacket: packet too large (%d)\n", totalLength);
  147.     }
  148.     } else {
  149.  
  150.     
  151.     /*
  152.      * Then copy enough data to bring buffer up to size.
  153.      */
  154.     
  155.     totalLength = sizeof(Net_EtherHdr);
  156.     
  157.     bufCount = 0;
  158.     for (bufCount = 0; bufCount < scatterGatherLength; 
  159.                 bufCount++,scatterGatherPtr++ ) {
  160.     
  161.         /*
  162.          * If is an empty buffer then skip it.
  163.          */
  164.     
  165.         length = scatterGatherPtr->length;
  166.         if (length == 0) {
  167.         continue;
  168.         }
  169.     
  170.         bufPtr = scatterGatherPtr->bufAddr;
  171.     
  172.         /*
  173.          * Compute the amount of data needed in the first buffer to make it
  174.          * a minumum size.
  175.          */
  176.     
  177.         amountNeeded = NET_LE_MIN_FIRST_BUFFER_SIZE - totalLength;
  178.         if (amountNeeded > 0 ) {
  179.         /*
  180.          * Still need more padding in first buffer.
  181.          */
  182.         if (length <= amountNeeded) {
  183.              /*
  184.               * Needs this entire length.
  185.               */
  186.              bcopy(bufPtr, firstBufferPtr, length);
  187.              totalLength += length;
  188.              firstBufferPtr += length;
  189.              /*
  190.               * Get the next segment of the scatter.
  191.               */
  192.              continue;
  193.         } else {
  194.             /*
  195.              * Needs only part of this buffer.
  196.              */
  197.              bcopy(bufPtr, firstBufferPtr, amountNeeded);
  198.              totalLength += amountNeeded;
  199.              /*
  200.               * Update the length and address for insertion into the
  201.               * buffer ring. firstBufferPtr is not used anymore in this
  202.               * loop.
  203.               */
  204.              length -= amountNeeded;
  205.              bufPtr += amountNeeded;
  206.              if (length == 0) {
  207.                 continue;
  208.              }
  209.     
  210.         }
  211.          }
  212. #if defined(sun3) || defined(sun4)
  213.         if (!reMapped) { 
  214.         /*
  215.          * Remap the packet into network addressible memory.
  216.          */
  217.         VmMach_NetMapPacket(scatterGatherPtr, 
  218.             scatterGatherLength-bufCount, newScatGathArr);
  219.         bufPtr = newScatGathArr->bufAddr + 
  220.                 (bufPtr - scatterGatherPtr->bufAddr);
  221.         scatterGatherPtr = newScatGathArr;
  222.         reMapped = TRUE;
  223.         }
  224. #endif
  225.         /*
  226.          * Add bufPtr of length length to the next buffer of the chain.
  227.          */
  228.         descPtr = NEXT_SEND(descPtr);
  229.         if (NetBfByteTest(descPtr->bits1, ChipOwned, 1)) {
  230.         /*
  231.          * Along as we only transmit one packet at a time, a buffer
  232.          * own by the chip is a serious problem.
  233.          */
  234.         printf("LE ethernet: Transmit buffer owned by chip.\n");
  235.         return (FAILURE);
  236.         }
  237.         descPtr->bufAddrLow = NET_LE_TO_CHIP_ADDR_LOW(bufPtr);
  238.         descPtr->bufAddrHigh = NET_LE_TO_CHIP_ADDR_HIGH(bufPtr);
  239.         NetBfByteSet(descPtr->bits1, StartOfPacket, 0);
  240.         NetBfByteSet(descPtr->bits1, EndOfPacket, 0);
  241.         descPtr->bufferSize = -length;
  242.  
  243.         totalLength += length;
  244.     }
  245.     }
  246.  
  247.     /*
  248.      * See if we need to update the size of the first buffer.
  249.      */
  250.  
  251.     if (totalLength < NET_LE_MIN_FIRST_BUFFER_SIZE) {
  252.     /*
  253.      * Since totalLength < NET_LE_MIN_FIRST_BUFFER_SIZE, descPtr should
  254.      * still point at the buffer desciptor for the first block.
  255.      * Just update its size. If the size is less than the minimum possible
  256.      * length, increase the length and send the garbage in the buffer.
  257.      */
  258.     descPtr->bufferSize = -totalLength;
  259.     if (totalLength < NET_ETHER_MIN_BYTES) {
  260.         descPtr->bufferSize = -NET_ETHER_MIN_BYTES;
  261.     } 
  262.     }
  263.     if (rpc_SanityCheck && (etherHdrPtr->type == NET_ETHER_SPRITE)) {
  264.     ReturnStatus     status;
  265.     status = Rpc_SanityCheck(scatterGatherLength, 
  266.             statePtr->curScatGathPtr, totalLength);
  267.     if (status != SUCCESS) {
  268.         panic("Sanity check failed on outgoing packet.\n");
  269.     }
  270.     }
  271.  
  272.     /*
  273.      * Finish off the packet.
  274.      */
  275.  
  276.     NetBfByteSet(descPtr->bits1, EndOfPacket, 1);
  277.  
  278.     /*
  279.      * Change the ownership to the chip. Avoid race conditions by doing it
  280.      * with the last buffer first.
  281.      */
  282.  
  283.     while (TRUE) {
  284.     NetBfByteSet(descPtr->bits1, ChipOwned, 1);
  285.     if (descPtr == statePtr->xmitDescNextPtr) {
  286.         break;
  287.     }
  288.     descPtr = PREV_SEND(descPtr);
  289.     }
  290.  
  291.     /*
  292.      * Give the chip a little kick.
  293.      */
  294.     NetBfShortSet(statePtr->regPortPtr->addrPort, AddrPort, NET_LE_CSR0_ADDR);
  295.     Mach_EmptyWriteBuffer();
  296.     statePtr->regPortPtr->dataPort = 
  297.         (NET_LE_CSR0_XMIT_DEMAND | NET_LE_CSR0_INTR_ENABLE);
  298.     return (SUCCESS);
  299.  
  300. }
  301.  
  302.  
  303. /*
  304.  *----------------------------------------------------------------------
  305.  *
  306.  * AllocateXmitMem --
  307.  *
  308.  *    Allocate kernel memory for transmission ring.    
  309.  *
  310.  * Results:
  311.  *    None.
  312.  *
  313.  * Side effects:
  314.  *    Device state structure is updated.
  315.  *
  316.  *----------------------------------------------------------------------
  317.  */
  318.  
  319. static void
  320. AllocateXmitMem(statePtr)
  321.     NetLEState        *statePtr;     /* State of the interface. */
  322. {
  323.     unsigned int    memBase;    
  324.  
  325.     /*
  326.      * Allocate the ring of transmission buffer descriptors.  
  327.      * The ring must start on 8-byte boundary.  
  328.      */
  329.     memBase = (unsigned int) BufAlloc(statePtr, 
  330.     (NET_LE_NUM_XMIT_BUFFERS * sizeof(NetLEXmitMsgDesc)) + 8);
  331.     /*
  332.      * Insure ring starts on 8-byte boundary.
  333.      */
  334.     if (memBase & 0x7) {
  335.     memBase = (memBase + 8) & ~0x7;
  336.     }
  337.     statePtr->xmitDescFirstPtr = (NetLEXmitMsgDesc *) memBase;
  338.  
  339.     /*
  340.      * Allocate the first buffer for a packet.
  341.      */
  342.     statePtr->firstDataBuffer = BufAlloc(statePtr, ((NET_LE_COPY_PACKET) ? 
  343.     NET_ETHER_MAX_BYTES : NET_LE_MIN_FIRST_BUFFER_SIZE));
  344.     statePtr->xmitMemAllocated = TRUE;
  345.     return;
  346. }
  347.  
  348. /*
  349.  *----------------------------------------------------------------------
  350.  *
  351.  * NetLEXmitInit --
  352.  *
  353.  *    Initialize the transmission queue structures.  This includes setting
  354.  *    up the transmission ring buffers.
  355.  *
  356.  * Results:
  357.  *    None.
  358.  *
  359.  * Side effects:
  360.  *    The transmission ring is initialized.
  361.  *
  362.  *----------------------------------------------------------------------
  363.  */
  364.  
  365. void
  366. NetLEXmitInit(statePtr)
  367.     NetLEState        *statePtr;     /* State of the interface. */
  368. {
  369.     int         bufNum;
  370.     volatile NetLEXmitMsgDesc    *descPtr;
  371.  
  372.  
  373.     if (!statePtr->xmitMemAllocated) {
  374.     AllocateXmitMem(statePtr);
  375.     }
  376.     statePtr->xmitMemInitialized = TRUE;
  377.  
  378.     /*
  379.      * Initialize the state structure to point to the ring. xmitDescFirstPtr
  380.      * is set by AllocateXmitMem() and never moved.
  381.      */
  382.     statePtr->xmitDescLastPtr = 
  383.         &(statePtr->xmitDescFirstPtr[NET_LE_NUM_XMIT_BUFFERS-1]);
  384.     statePtr->xmitDescNextPtr = statePtr->xmitDescFirstPtr;
  385.  
  386.     descPtr = statePtr->xmitDescFirstPtr;
  387.     for (bufNum = 0; bufNum < NET_LE_NUM_XMIT_BUFFERS; bufNum++, descPtr++) { 
  388.     bzero((char *) descPtr, sizeof(NetLEXmitMsgDesc));
  389.     }
  390.     statePtr->transmitting = FALSE;
  391.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  392.     return;
  393. }
  394.  
  395.  
  396. /*
  397.  *----------------------------------------------------------------------
  398.  *
  399.  * NetLEXmitDone --
  400.  *
  401.  *    This routine will process a completed transmit command.  It will
  402.  *    check for errors and update the transmission ring pointers.
  403.  *
  404.  * Results:
  405.  *    FAILURE if problem is found.
  406.  *
  407.  * Side effects:
  408.  *    None.
  409.  *
  410.  *----------------------------------------------------------------------
  411.  */
  412.  
  413. ReturnStatus
  414. NetLEXmitDone(statePtr)
  415.     NetLEState        *statePtr;     /* State of the interface. */
  416. {
  417.     register    volatile NetXmitElement         *xmitElementPtr;
  418.     register    volatile NetLEXmitMsgDesc    *descPtr;
  419.     ReturnStatus            status;
  420.     char                *buffer; 
  421.  
  422.     descPtr = statePtr->xmitDescNextPtr;
  423.  
  424.     /*
  425.      * If there is nothing that is currently being sent then something is
  426.      * wrong.
  427.      */
  428.     if (statePtr->curScatGathPtr == (Net_ScatterGather *) NIL) {
  429.     printf( "NetLEXmitDone: No current packet\n.");
  430.     status = FAILURE;
  431.     goto exit;
  432.     }
  433.  
  434.     if (NetBfByteTest(descPtr->bits1, ChipOwned, 1)) {
  435.     printf("LE ethernet: Bogus xmit interrupt. Buffer owned by chip.\n");
  436.     status = FAILURE;
  437.     goto exit;
  438.     }
  439.     if (NetBfByteTest(descPtr->bits1, StartOfPacket, 0)) {
  440.     printf("LE ethernet: Bogus xmit interrupt. Buffer not start of packet.\n");
  441.     status = FAILURE;
  442.     goto exit;
  443.     }
  444.  
  445.     /*
  446.      * Check for errors.
  447.      */
  448.     while (TRUE) {
  449.  
  450.     if (NetBfByteTest(descPtr->bits1, Error, 1)) {
  451.         statePtr->stats.xmitPacketsDropped++;
  452.         if (NetBfShortTest(descPtr->bits2, LateCollision, 1)) {
  453.         printf("LE ethernet: Transmit late collision.\n");
  454.         }
  455.         if (NetBfShortTest(descPtr->bits2, LostCarrier, 1)) {
  456.         printf("LE ethernet: Lost carrier.\n");
  457.         }
  458.         /*
  459.          * Lost of carrier seems to also causes late collision.
  460.          * Print only one of the messages.
  461.          */
  462.         if ((NetBfShortTest(descPtr->bits2, LateCollision, 1)) &&
  463.         (NetBfShortTest(descPtr->bits2, LostCarrier, 0))) {
  464.         printf("LE ethernet: Transmit late collision.\n");
  465.         }
  466.         if (NetBfShortTest(descPtr->bits2, RetryError, 1)) {
  467.         statePtr->stats.xmitCollisionDrop++;
  468.         statePtr->stats.collisions += 16;
  469.         printf("LE ethernet: Too many collisions.\n");
  470.         }
  471.         if (NetBfShortTest(descPtr->bits2, UnderflowError, 1)) {
  472.         printf("LE ethernet: Memory underflow error.\n");
  473.         status = FAILURE;
  474.         goto exit;
  475.         }
  476.     }
  477.     if (NetBfShortTest(descPtr->bits2, XmitBufferError, 1)) {
  478.         printf("LE ethernet: Transmit buffering error.\n");
  479.         status = FAILURE;
  480.         goto exit;
  481.     }
  482.     if (NetBfByteTest(descPtr->bits1, OneRetry, 1)) {
  483.         statePtr->stats.collisions++;
  484.     }
  485.     if (NetBfByteTest(descPtr->bits1, Retries, 1)) {
  486.         /*
  487.          * Two is more than one.  
  488.          */
  489.         statePtr->stats.collisions += 2;    /* Only a guess. */
  490.     }
  491.  
  492.     buffer = (char *) NET_LE_FROM_CHIP_ADDR(statePtr, 
  493.         descPtr->bufAddrHigh, descPtr->bufAddrLow);
  494.  
  495.     if (NetBfByteTest(descPtr->bits1, EndOfPacket, 1)) {
  496.         break;
  497.     }
  498.  
  499.     descPtr = NEXT_SEND(descPtr);
  500.     if (descPtr == statePtr->xmitDescNextPtr) {
  501.         panic("LE ethernet: Transmit ring with no end of packet.\n");
  502.     }
  503.     if (NetBfByteTest(descPtr->bits1, ChipOwned, 1)) {
  504.         printf("LE ethernet: Transmit Buffer owned by chip.\n");
  505.         status = FAILURE;
  506.         goto exit;
  507.     }
  508.     }
  509.  
  510.     statePtr->stats.packetsSent++;
  511.  
  512.     /*
  513.      * Update the ring pointer to point at the next buffer to use.
  514.      */
  515.  
  516.     statePtr->xmitDescNextPtr = NEXT_SEND(descPtr);
  517.  
  518.     /*
  519.      * Mark the packet as done.
  520.      */
  521.     statePtr->curScatGathPtr->done = TRUE;
  522.     if (statePtr->curScatGathPtr->mutexPtr != (Sync_Semaphore *) NIL) {
  523.     NetOutputWakeup(statePtr->curScatGathPtr->mutexPtr);
  524.     }
  525.  
  526.     /*
  527.      * If there are more packets to send then send the first one on
  528.      * the queue.  Otherwise there is nothing being transmitted.
  529.      */
  530.     status = SUCCESS;
  531.     if (statePtr->resetPending == TRUE) {
  532.     goto exit;
  533.     }
  534.     if (!List_IsEmpty(statePtr->xmitList)) {
  535.     xmitElementPtr = (NetXmitElement *) List_First(statePtr->xmitList);
  536.     status = OutputPacket(xmitElementPtr->etherHdrPtr,
  537.              xmitElementPtr->scatterGatherPtr,
  538.              xmitElementPtr->scatterGatherLength, statePtr);
  539.     List_Move((List_Links *) xmitElementPtr, 
  540.           LIST_ATREAR(statePtr->xmitFreeList));
  541.     } else {
  542.     statePtr->transmitting = FALSE;
  543.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  544.     }
  545. exit:
  546.     /*
  547.      * This assumes that whatever calls us will reset the chip if we return
  548.      * anything other than SUCCESS.  This way we avoid resetting the chip 
  549.      * twice in a row.
  550.      */
  551.     if ((statePtr->resetPending == TRUE) && (status == SUCCESS)) {
  552.     statePtr->transmitting = FALSE;
  553.     NetLEReset(statePtr->interPtr);
  554.     }
  555.     if (status != SUCCESS) {
  556.     statePtr->transmitting = FALSE;
  557.     }
  558.     return (status);
  559. }
  560.  
  561.  
  562. /*
  563.  *----------------------------------------------------------------------
  564.  *
  565.  * NetLEOutput --
  566.  *
  567.  *    Output a packet.  The procedure is to either put the packet onto the 
  568.  *    queue of outgoing packets if packets are already being sent, or 
  569.  *    otherwise to send the packet directly.  The elements of the scatter 
  570.  *    array which come into this routine must satisfy the following two 
  571.  *    properties:
  572.  *
  573.  *
  574.  * Results:
  575.  *    SUCCESS if the packet was queued to the chip correctly, otherwise
  576.  *    a standard Sprite error code.
  577.  *
  578.  * Side effects:
  579.  *    Queue of packets modified.
  580.  *
  581.  *----------------------------------------------------------------------
  582.  */
  583.  
  584. ReturnStatus
  585. NetLEOutput(interPtr, hdrPtr, scatterGatherPtr, scatterGatherLength, rpc,
  586.         statusPtr)
  587.     Net_Interface    *interPtr;    /* The network interface. */
  588.     Address        hdrPtr;        /* Packet header. */
  589.     register    Net_ScatterGather    *scatterGatherPtr; /* Data portion of 
  590.                                 * the packet. */
  591.     int            scatterGatherLength;    /* Length of data portion gather
  592.                          * array. */
  593.     Boolean        rpc;            /* Is this an RPC packet? */
  594.     ReturnStatus    *statusPtr;        /* Status from sending packet.*/
  595. {
  596.     register    NetXmitElement        *xmitPtr;
  597.     ReturnStatus            status;
  598.     NetLEState                *statePtr;
  599.     Net_EtherHdr            *etherHdrPtr = (Net_EtherHdr *) hdrPtr;
  600.  
  601.     statePtr = (NetLEState *) interPtr->interfaceData;
  602.     MASTER_LOCK(&interPtr->mutex);
  603.  
  604.     statePtr->stats.packetsOutput++;
  605.  
  606.     /*
  607.      * Verify that the scatter gather array is not too large.  There is a fixed
  608.      * upper bound because the list of transmit buffers is preallocated.
  609.      */
  610.  
  611.     if (scatterGatherLength >= NET_LE_NUM_XMIT_BUFFERS) {
  612.     scatterGatherPtr->done = TRUE;
  613.  
  614.     printf("LE ethernet: Packet in too many pieces\n");
  615.     status = FAILURE;
  616.     goto exit;
  617.     }
  618.  
  619.  
  620.     /*
  621.      * See if the packet is for us.  In this case just copy in the packet
  622.      * and call the higher level routine.
  623.      */
  624.  
  625.     if (NET_ETHER_COMPARE(statePtr->etherAddress, etherHdrPtr->destination)) {
  626.     int i, length;
  627.  
  628.         length = sizeof(Net_EtherHdr);
  629.         for (i = 0; i < scatterGatherLength; i++) {
  630.             length += scatterGatherPtr[i].length;
  631.         }
  632.  
  633.         if (length <= NET_ETHER_MAX_BYTES) {
  634.         register Address bufPtr;
  635.  
  636.         etherHdrPtr->source = statePtr->etherAddress;
  637.  
  638.         bufPtr = (Address)statePtr->loopBackBuffer;
  639.         bcopy((Address)etherHdrPtr, bufPtr, sizeof(Net_EtherHdr));
  640.         bufPtr += sizeof(Net_EtherHdr);
  641.             Net_GatherCopy(scatterGatherPtr, scatterGatherLength, bufPtr);
  642.  
  643.         Net_Input(interPtr, (Address)statePtr->loopBackBuffer, length);
  644.         }
  645.  
  646.         scatterGatherPtr->done = TRUE;
  647.  
  648.     status = SUCCESS;
  649.     if (statusPtr != (ReturnStatus *) NIL) {
  650.         *statusPtr = SUCCESS;
  651.     }
  652.     goto exit;
  653.     }
  654.  
  655.     /*
  656.      * If no packet is being sent then go ahead and send this one.
  657.      */
  658.  
  659.     if (!statePtr->transmitting) {
  660.     status = 
  661.         OutputPacket(etherHdrPtr, scatterGatherPtr, scatterGatherLength,
  662.             statePtr);
  663.     if (status != SUCCESS) {
  664.         NetLERestart(interPtr);
  665.     } else if (statusPtr != (ReturnStatus *) NIL) {
  666.         *statusPtr = SUCCESS;
  667.     }
  668.     goto exit;
  669.     }
  670.     /*
  671.      * There is a packet being sent so this packet has to be put onto the
  672.      * transmission queue.  Get an element off of the transmission free list.  
  673.      * If none available then drop the packet.
  674.      */
  675.  
  676.     if (List_IsEmpty(statePtr->xmitFreeList)) {
  677.         scatterGatherPtr->done = TRUE;
  678.     status = FAILURE;
  679.     goto exit;
  680.     }
  681.  
  682.     xmitPtr = (NetXmitElement *) List_First((List_Links *) statePtr->xmitFreeList);
  683.  
  684.     List_Remove((List_Links *) xmitPtr);
  685.  
  686.     /*
  687.      * Initialize the list element.
  688.      */
  689.  
  690.     xmitPtr->etherHdrPtr = etherHdrPtr;
  691.     xmitPtr->scatterGatherPtr = scatterGatherPtr;
  692.     xmitPtr->scatterGatherLength = scatterGatherLength;
  693.  
  694.     /* 
  695.      * Put onto the transmission queue.
  696.      */
  697.  
  698.     List_Insert((List_Links *) xmitPtr, LIST_ATREAR(statePtr->xmitList)); 
  699.  
  700.     if (statusPtr != (ReturnStatus *) NIL) {
  701.     *statusPtr = SUCCESS;
  702.     }
  703.     status = SUCCESS;
  704. exit:
  705.     MASTER_UNLOCK(&interPtr->mutex);
  706.     return SUCCESS;
  707. }
  708.  
  709.  
  710. /*
  711.  *----------------------------------------------------------------------
  712.  *
  713.  * NetLEXmitDrop --
  714.  *
  715.  *    Drop the current packet.  Called at the beginning of the
  716.  *    restart sequence, before curScatGathPtr is reset to NIL.
  717.  *
  718.  * Results:
  719.  *    None.
  720.  *
  721.  * Side effects:
  722.  *    Current scatter gather pointer is reset and processes waiting
  723.  *    for synchronous output are notified.
  724.  *
  725.  *----------------------------------------------------------------------
  726.  */
  727. void
  728. NetLEXmitDrop(statePtr)
  729.     NetLEState        *statePtr;     /* State of the interface. */
  730. {
  731.     if (statePtr->curScatGathPtr != (Net_ScatterGather *) NIL) {
  732.     statePtr->curScatGathPtr->done = TRUE;
  733.     if (statePtr->curScatGathPtr->mutexPtr != (Sync_Semaphore *) NIL) {
  734.         NetOutputWakeup(statePtr->curScatGathPtr->mutexPtr);
  735.     }
  736.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  737.     }
  738.     return;
  739. }
  740.  
  741. /*
  742.  *----------------------------------------------------------------------
  743.  *
  744.  * NetLEXmitRestart --
  745.  *
  746.  *    Restart transmission of packets at the end of the restart
  747.  *    sequence, after a chip reset.
  748.  *
  749.  * Results:
  750.  *    None.
  751.  *
  752.  * Side effects:
  753.  *    Output queue started up.
  754.  *
  755.  *----------------------------------------------------------------------
  756.  */
  757. void
  758. NetLEXmitRestart(statePtr)
  759.     NetLEState        *statePtr;     /* State of the interface. */
  760. {
  761.     NetXmitElement    *xmitElementPtr;
  762.     ReturnStatus    status;
  763.  
  764.     /*
  765.      * Start output if there are any packets queued up.
  766.      */
  767.     if (!List_IsEmpty(statePtr->xmitList)) {
  768.     xmitElementPtr = (NetXmitElement *) List_First(statePtr->xmitList);
  769.     status = OutputPacket(xmitElementPtr->etherHdrPtr,
  770.              xmitElementPtr->scatterGatherPtr,
  771.              xmitElementPtr->scatterGatherLength, statePtr);
  772.     if (status != SUCCESS) {
  773.         panic("LE ethernet: Can not output first packet on restart.\n");
  774.     }
  775.     List_Move((List_Links *) xmitElementPtr, 
  776.           LIST_ATREAR(statePtr->xmitFreeList));
  777.     } else {
  778.     statePtr->transmitting = FALSE;
  779.     statePtr->curScatGathPtr = (Net_ScatterGather *) NIL;
  780.     }
  781.     return;
  782. }
  783.